from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.contrib.auth.decorators import login_required
from django.utils import simplejson
from django.core.paginator import Paginator, EmptyPage
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from tagging.models import Tag, TaggedItem

from ask.models import Question, Answer
from ask.forms import AddAnswerForm, AddQuestionForm
from common.funcs import can_do

notification = None

def questions_by_cat(request, tag=None, dir='', order='publish', page=1, filter_args={}, template_name='ask/question_list.html'):
    list = Question.public.all()
    title = None

    list = list.filter(**filter_args)
    if order=='publish':
        list = list.order_by('-pub_date')
    elif order=='score':
        list = list.order_by('-score')
    elif order=='views':
        list = list.order_by('-views')
    elif order=='answers':
        list = list.order_by('-answer_count')
    elif order=='unsolved':
        list = list.order_by('is_solved')

    if tag is not None:
        try:
            the_tag = Tag.objects.get(name=tag)
            list = TaggedItem.objects.get_by_model(list, the_tag)
        except Tag.DoesNotExist:
            return HttpResponseRedirect(reverse('ask_index'))
        
    paginator = Paginator(list,20)

    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', page))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        lst = paginator.page(page)
    except (EmptyPage):
        lst = paginator.page(paginator.num_pages)
    
    c = RequestContext(request, {'page':lst, 'title': title })
    return render_to_response(template_name, c)

def questions_of(request, username, action='asked', rfrom='ask', order='publish', page=1, filter_args={}, template_name='ask/question_list.html'):
    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        return HttpResponseRedirect(reverse('ask_index'))
    if action=='asked':
        list = Question.public.filter(user=user)
    else:
        tmp = Answer.public.filter(user=user).values_list('question')
        list = Question.public.filter(pk__in=tmp)
    title = _("Questions of") + u' %s' % user

    list = list.filter(**filter_args)
    if order=='publish':
        list = list.order_by('-pub_date')
    elif order=='score':
        list = list.order_by('-score')
    elif order=='views':
        list = list.order_by('-views')
    elif order=='answers':
        list = list.order_by('-answer_count')
    elif order=='unsolved':
        list = list.order_by('is_solved')
    
    paginator = Paginator(list,20)

    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', page))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        lst = paginator.page(page)
    except (EmptyPage):
        lst = paginator.page(paginator.num_pages)
    
    c = RequestContext(request, {'page':lst, 'title': title, 'author': user })
    return render_to_response(template_name, c)

@login_required
def create_question(request, qid=None, template_name='ask/create_question.html'):
    d = {'user': request.user}
    if qid is not None:
        try:
            q = Question.public.get(pk=qid)
            d['instance'] = q
        except Question.DoesNotExist:
            request.user.message_set.create(message="error|No such question.")
            return HttpResponseRedirect(reverse('ask_index'))

        ok = False
        ok = ok or q.get_author==request.user
        ok = ok or request.user.has_perm('%(app)s.change_%(model)s' % {'app':q.get_app(), 'model':q.get_model()})
        if not ok:
            request.user.message_set.create(message="error|You have no permission to edit this object.")
            return HttpResponseRedirect(q.get_absolute_url())
        
    form = AddQuestionForm(**d)
    if request.method=="POST":
        form = AddQuestionForm(request.POST, **d)
        if form.is_valid():
            q = form.save()
            request.user.message_set.create(message="Your question was successfully posted.")
            return HttpResponseRedirect(q.get_absolute_url())
        else:
            request.user.message_set.create(message="error|Your question was not posted.")
    c = RequestContext(request, {'form': form})
    return render_to_response(template_name, c)     


def question_detail(request, qid, page=1, order='score', filter_args={}, template_name='ask/question_detail.html'):
    try:
        object = Question.public.get(pk=qid)
    except Question.DoesNotExist:
        return HttpResponseRedirect(reverse('ask_index'))

    form = AddAnswerForm(user=request.user, question=object)
    if (request.user.is_authenticated()):
        if request.method == "POST":
            form = AddAnswerForm(request.POST, user=request.user, question=object)
            if form.is_valid():
                form.save()
                request.user.message_set.create(message="Your answer was successfully posted.")
                return HttpResponseRedirect(request.path)
            else:
                request.user.message_set.create(message="error|Your answer was not posted.")

    list = object.answer_set.all()

    list = list.filter(**filter_args)
    if order=='publish':
        list = list.order_by('-pub_date')
    if order=='rpublish':
        list = list.order_by('pub_date')
    elif order=='score':
        list = list.order_by('-score')

    paginator = Paginator(list, 10)

    # Make sure page request is an int. If not, deliver first page.
    try:
        page = int(request.GET.get('page', page))
    except ValueError:
        page = 1

    # If page request (9999) is out of range, deliver last page of results.
    try:
        lst = paginator.page(page)
    except (EmptyPage):
        lst = paginator.page(paginator.num_pages)
 
    c = RequestContext(request, {'object': object, 'form':form, 'page': lst, 'ans_count': paginator.count})
    return render_to_response(template_name, c)

@login_required
def accept_answer(request, aid):
    next = request.GET.get('next',reverse('ask_index'))
    data = {'success': True}
    aj = not (request.method == "POST")
    try:
        a = Answer.public.get(pk=aid)
        if request.user.is_authenticated() and a.question.user == request.user:            
            a.is_accepted = not a.is_accepted
            a.save()
            if aj:
                if a.is_accepted:
                    request.user.message_set.create(message="Answer is accepted.")
                else:
                    request.user.message_set.create(message="Answer was unmarked.")
            if notification:
                notification.send([a.question.user], "answer_accepted", {"answer": a})
        else:
            data = {'success': False}
            if aj:
                request.user.message_set.create(message="error|You are not allowed to accept the answer.")
    except Answer.DoesNotExist:
        if aj:
            request.user.message_set.create(message="error|No such answer.")
        data = {'success': False}
    if not aj:
        json = simplejson.dumps(data)
        return HttpResponse(json, mimetype="json/application")
    else:
        return HttpResponseRedirect(next)
    
@login_required
def create_answer(request, qid, aid, template_name='ask/create_answer.html'):
    next = request.GET.get('next',reverse('ask_index'))
    d = {'user': request.user}
    try:
        a = Answer.public.get(pk=aid, question__pk=qid)
        q = Question.public.get(pk=qid)
        d['instance'] = a
        d['question'] = q
    except (Question.DoesNotExist, Answer.DoesNotExist):
        request.user.message_set.create(message="error|No such answer.")
        return HttpResponseRedirect(next)

    ok = False
    ok = ok or a.get_author==request.user
    ok = ok or request.user.has_perm('%(app)s.change_%(model)s' % {'app':a.get_app(), 'model':a.get_model()})
    if not ok:
        request.user.message_set.create(message="error|You have no permission to edit this object.")
        return HttpResponseRedirect(a.get_absolute_url())


    form = AddAnswerForm(**d)
    if request.method=="POST":
        form = AddAnswerForm(request.POST, **d)
        if form.is_valid():
            form.save()
            request.user.message_set.create(message="Your answer was successfully posted.")
            return HttpResponseRedirect(next)
        else:
            request.user.message_set.create(message="error|Your answer was not posted.")
    c = RequestContext(request, {'form': form})
    return render_to_response(template_name, c)     

@login_required
def delete_question(request, qid):
    next = request.GET.get('next',reverse('ask_index'))
    user = request.user
        
    try:
        q = Question.private.get(pk=qid)
    except Question.DoesNotExist:
        request.user.message_set.create(message="error|Question was not deleted.")
        return HttpResponseRedirect(next)

    if (can_do(user, "delete_question", q.user)):
        q.delete()
        request.user.message_set.create(message="OK")
    else:
        request.user.message_set.create(message="error|You are not allowed to delete this question.")
    
    return HttpResponseRedirect(next)
